package com.szjlc.torna.exception;

import com.szjlc.torna.result.BusinessResult;
import javax.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理
 * @author steve
 * @since 2022-11-19 14:43
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * {@link @RequestBody}
     * {@link @RequestBody} 参数校验不通过时抛出的异常处理
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public BusinessResult<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        StringBuilder sb = new StringBuilder();
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            sb.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage()).append(", ");
        }

        String message = sb.toString();

        if (message.trim().endsWith(",")) {
            message = message.substring(0, message.length() - 1);
        }

        // springframwork.StringUtils
        if (StringUtils.hasText(message)) {
            return BusinessResult.fail(HttpStatus.BAD_REQUEST.value(), message);
        }
        return BusinessResult.fail(HttpStatus.BAD_REQUEST.value(), e.getMessage());
    }

    /** 捕获 {@link NullPointerException } 异常 */
    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ExceptionHandler(value = NullPointerException.class)
    public BusinessResult<?> handleForbiddenException(NullPointerException e) {
        return BusinessResult.fail(HttpStatus.FORBIDDEN);
    }

    /**
     * {@link ConstraintViolationException}
     * {@code @PathVariable} 和 {@code @RequestParam} 参数校验不通过时抛出的异常处理
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = ConstraintViolationException.class)
    public BusinessResult<?> handleConstraintViolationException(ConstraintViolationException e) {
        if (StringUtils.hasText(e.getMessage())) {
            return BusinessResult.fail(HttpStatus.BAD_REQUEST.value(), e.getMessage());
        }
        return BusinessResult.fail(HttpStatus.BAD_REQUEST);
    }

    /**
     * 顶级异常捕获并统一处理，当其他异常无法处理时候选择使用
     * 用于兜底处理
     */
    @ExceptionHandler(value = Exception.class)
    public BusinessResult<?> handle(Exception e) {
        return BusinessResult.fail(HttpStatus.BAD_REQUEST.value(), e.getMessage());
    }


}
